Git og versionskontrol

Jeppe Fjeldgaard Qvist

2025-09-24

Dagens program

  • Filsystemer og -hierakier (delvis genopfriskning af de indledende forelæsninger)
  • Git (Hvad er det?)
  • Git (Hvordan bruger vi det?)
  • Workshop (i studiegrupperne; opsætning af mini-projekter)

Lagring af data på en computer

Hvad er en fil?

En sekvens af data, gemt som en sammenhængende enhed:

  • Binære data
  • Tekst
  • Programmer
  • … osv.

Filnavn og -udvidelse (fx projekt.docx):

  • Basenavn: projekt
  • Filudvidelse: .docx, angiver hvilken data filen indeholder og hvordan den skal læses

Metaelementer:

  • Filstørrelse: “hvor mange bytes optager filen”
  • Oprettelse- og ændringsdato
  • Filens type
  • Ejerskab
  • Adgangsrettigheder
  • … osv.

Filorganisering

Spg.: Hvad vil det sige at filer er organiseret? Hvorfor er det nødvendigt? Og hvordan organisere I filer på jeres computer?

  • Referer til hvordan vores filer (data) og mapper (directories) er struktureret og lagret på vores lagringsenhed (harddisk, SSD, ekstern enhed, …).

  • Denne struktur bestemmer hvordan data hentes og gemmes, og gør det muligt for brugeren eller programmer at finde, tilgå og anvende filer.

Mao.: Hvor skal computeren kigge, når den vil interagere med lagret data, og hvor skal den putte dataen hen når den er færdig med at interagere med den.

Mapper: grundlaget for organiseringen

  • En mappe (directory) er en container, som indeholder filer og andre mapper, og danner grundlaget for en hierakisk struktur (tree-/træstruktur).

  • (Træ-)hierakiet giver en logisk og navigérbar organisering på computeren.

Hierakiske strukturer

… en hierakisk struktur er derfor den almindelige måde at organisere filer og mapper i operativsystemer i dag.

  • Opbygningen er med afsæt i en root-mappe, som indeholder undermapper og filer. Herfra indeholder hver undermappe andre undermapper og filer, hvilket danner et træ af mapper og filer, hvis vi zoomer ud.
    • root directory: I Unix-systemer (MacOS, Linux) betegnes den /. I Windows er der en root-mappe i hvert drev, betegnet med bogstavet for drevet, fx C:
    • Undermapper: Mapper, der findes inde i andre mapper, fx /home/user/documents eller C:.

Et filsystem

UNIX (MacOS, Linux)

/
├── bin                  # Vigtige eksekverbare systemfiler
├── sbin                 # Systemadministrative eksekverbare filer
├── etc                  # Systemkonfigurationsfiler
├── home                 # Brugermapper (personlige filer)
│   └── jeppe            # Brugeren "jeppe"'s hjemmemappe
│       ├── Documents    # jeppes dokumenter
│       ├── Downloads    # jeppes downloadede filer
│       ├── Music        # jeppes musikfiler
│       ├── Pictures     # jeppes billeder
│       ├── Videos       # jeppes videofiler
│       └── Projects     # Personlige kodeprojekter og scripts
│           └── snake_game
│               ├── main.py # Python-kode til et snake-spil
│               └── assets  # Grafikfiler til spillet
├── root                 # Superbrugerens hjemmemappe
├── usr                  # Bruger- og systemprogrammer
│   ├── bin              # Programmer installeret til brugere
│   ├── lib              # Systemets biblioteker
│   └── local            # Lokalt installerede programmer
├── var                  # Variable data som logs og mails
│   ├── log              # Systemets logfiler
│   └── tmp              # Midlertidige filer
├── tmp                  # Midlertidige filer (slettes ved genstart)
├── dev                  # Systemets enheder som harddiske og terminaler
├── mnt                  # Monteringspunkt for midlertidige enheder
│   └── usb-drive        # En USB-nøgle monteret her
└── media                # Monteringspunkt for eksterne enheder
    └── jeppe-usb        # jeppes eksterne harddisk hvis monteret
Windows

C:\
├── Program Files            # Programmer installeret for alle brugere
├── Program Files (x86)      # 32-bit versioner (på 64-bit systemer)
├── Users                    # Brugermapper (til hver bruger på systemet)
│   └── jeppe                # Brugeren "jeppe"'s hjemmemappe
│       ├── Documents        # jeppes dokumenter
│       ├── Downloads        # jeppes downloadede filer
│       ├── Music            # jeppes musikfiler
│       ├── Pictures         # jeppes billeder
│       ├── Videos           # jeppes videofiler
│       ├── Desktop          # Filer og genveje på jeppes skrivebord
│       ├── AppData          # jeppes personlige app-data og indstillinger
│       └── Projects         # Personlige kodeprojekter og scripts
│           └── snake_game
│               ├── main.py  # Python-kode til et snake-spil
│               └── assets   # Grafikfiler til spillet
├── Windows                  # Operativsystemets filer
│   ├── System32             # Vigtige systemfiler 
│   └── Temp                 # Midlertidige filer, der bruges af systemet
├── ProgramData              # Data, der deles af applikationer på systemet
└── Temp                     # Midlertidige filer

Terminalen: interaktion med computeren (og filsystemet)

Terminalen er det, der giver os adgang til kommandolinjegrænsefladen (CLI). Selvom den har miste meget af sin position blandt den gennemsnitlige computer-bruger, grundet fremkomsten ad grafiske brugergrænseflader (GUI), er den fortsat en meget effektiv måde at interagere med computeren. Særligt på Unix-systemer.

Når vi anvender CLI, bruger vi en shell, der er et program til fortolkning af kommandoer. De to mest almindelige shell-programmer er:

  • Bash (Bourne Again Shell): Standard på mange Linux-distributioner og tidligere på macOS.
  • Zsh (Z Shell): Standard på macOS fra og med version 10.15 Catalina.

For jer, vil der næppe komme en situation, hvor I vil opleve en forskel på de to. Begge kan tolke alle standard kommandoer. Zsh er dog ofte omtalt som mere brugervenligt og har flere muligheder for personliggørelse, men bash er mere end tilstrækkeligt.

Versionskontrol: Installation af Git i fællesskab

Git og organisering af arbejde

/projektarbejde
└──/backup
    ├── projekt_281024.docx
    ├── projekt_311024.docx
    ├── projekt_041224.docx
    ├── projekt_final.docx
    ├── projekt_final2.docx
    ├── projekt_final3.docx
    ├── projekt_final_final.docx
    └── projekt_FINAL.docx

Versionskontrol

Versionkontrol er et system (software), der holder styr på ændringer af filer over tid, der gør det muligt at genskabe vores tidligere arbejde. Virker for (stort set) alle filer.

På større projekter—hvor flere er involveret—er det vigtigt at have kontrol over, hvem der foretager ændringer, hvilke ændringer der er blevet foretaget, og hvordan man kan rulle tilbage til tidligere versioner, hvis noget går galt.

“[Git] allows you to revert selected files back to a previous state, revert the entire project back to a previous state, compare changes over time, see who last modified something that might be causing a problem, who introduced an issue and when, and more.”

Formål

I et langsigtet perspektiv vil Git hjælpe dig med at holde et projekt organiseret, muliggøre (mere) effektivt samarbejde og sikre, at vi altid har en backup af dine fremskridt.

Tænk på det som en avanceret “fortryd”-funktion for hele projekter.

/projektarbejde
└──/backup
    ├── projekt_281024.docx
    ├── projekt_311024.docx
    ├── projekt_041224.docx
    ├── projekt_final.docx
    ├── projekt_final2.docx
    ├── projekt_final3.docx
    ├── projekt_final_final.docx
    └── projekt_FINAL.docx
/projektarbejde
├── .git      <- Git's skjulte data
└── projekt.docx

Versionskontrol

A local version control system is a local database located on your local computer, in which every file change is stored as a patch. Every patch set contains only the changes made to the file since its last version. In order to see what the file looked like at any given moment, it is necessary to add up all the relevant patches to the file in order until that given moment.

The main problem with this is that everything is stored locally. If anything were to happen to the local database, all the patches would be lost. If anything were to happen to a single version, all the changes made after that version would be lost.

Also, collaborating with other developers or a team is very hard or nearly impossible.

A centralized version control system has a single server that contains all the file versions. This enables multiple clients to simultaneously access files on the server, pull them to their local computer or push them onto the server from their local computer. This way, everyone usually knows what everyone else on the project is doing. Administrators have control over who can do what.

This allows for easy collaboration with other developers or a team.

The biggest issue with this structure is that everything is stored on the centralized server. If something were to happen to that server, nobody can save their versioned changes, pull files or collaborate at all. Similar to Local Version Control, if the central database became corrupted, and backups haven’t been kept, you lose the entire history of the project except whatever single snapshots people happen to have on their local machines.

With distributed version control systems, clients don’t just check out the latest snapshot of the files from the server, they fully mirror the repository, including its full history. Thus, everyone collaborating on a project owns a local copy of the whole project, i.e. owns their own local database with their own complete history.

With this model, if the server becomes unavailable or dies, any of the client repositories can send a copy of the project’s version to any other client or back onto the server when it becomes available. It is enough that one client contains a correct copy which can then easily be further distributed.

Git i praksis

Den “usynlige” .git mappe skaber vi med Git-kommandoen:

git init

Kommandoen skaber en ny undermappe (.git) og er “skelettet” for vores repository. Denne mappe indeholder alle Git’s interne data, der bruges til at spore og administrere versionshistorikken for dit projekt.

I skal være opmærksom på hvilken mappe I befinder jer i, når i kører git init. Fremgangen skal være:

cd <absolut eller relativ stil>
git init

Git i praksis

Versionsstyringsprocessen med afsæt i .git skelletet består af 3 stadier:

  • Working Directory: den mappe, hvor vi kørte git init. Alt der ændres her spores af Git, men det gemmes (committes) ikke automatisk
  • Staging Area: De ændringer, som du ønsker registreret i næste commit bliver flyttet til et staging area ved git add .. Det er ikke som sådan et “sted”, men et snarer et “tag” til de filer, som Git skal gemme. Ingen ændringer er blevet gemt endnu.
  • Repository: Når vi bruger kommandoen git commit -m “besked” gemmes alt staged data i vores Git-repository og alle ændringer siden sidste commit bliver en permanent del af projektets versionshistorik.

Fælles øvelse

  1. Opret en bruger på GitHub og hent GitHub Desktop
  2. Én i studiegrupper opretter et repository på GitHub
  3. Denne person laver følgende fil med koden: print("Første commit")
  4. Den næste kloner repositoriet ned på egen computer
  5. Ændrer koden til: print("Første commit + anden commit") og “pusher”
  6. Tredje person gør det samme, tilføjer: print("Første commit + anden commit + tredje commit")
1. git pull     📥 (hent seneste ændringer)
2. Arbejd       💻 (skriv kode)  
3. git add      📋 (stage ændringer)
4. git commit   💾 (gem lokalt)
5. git push     📤 (del med andre)

Hvis der er tid tilbage, så lav i studiegruppen et repository til jeres mini-projekt.